package com.ikas.ai.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;

/**
 * 通信格式转换
 * Java和一些windows编程语言如c、c++所写的网络程序进行通讯时，需要进行相应的转换 高、低字节之间的转换 windows的字节序为低字节开头
 * linux,unix的字节序为高字节开头 java则无论平台变化，都是高字节开头
 */
public class FormatTransfer {

    private static Logger logger = LoggerFactory.getLogger(FormatTransfer.class);

    private FormatTransfer() {

    }

    /**
     * 将int转为低字节在前，高字节在后的byte数组
     * @param n int
     * @return byte[]
     */
    public static byte[] toLH(int n) {
        byte[] b = new byte[4];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        b[2] = (byte) (n >> 16 & 0xff);
        b[3] = (byte) (n >> 24 & 0xff);
        return b;
    }

    /**
     * 将int转为高字节在前，低字节在后的byte数组
     * @param n int
     * @return byte[]
     */
    public static byte[] toHH(int n) {
        byte[] b = new byte[4];
        b[3] = (byte) (n & 0xff);
        b[2] = (byte) (n >> 8 & 0xff);
        b[1] = (byte) (n >> 16 & 0xff);
        b[0] = (byte) (n >> 24 & 0xff);
        return b;
    }

    /**
     * 将short转为低字节在前，高字节在后的byte数组
     * @param n short
     * @return byte[]
     */
    public static byte[] toLH(short n) {
        byte[] b = new byte[2];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        return b;
    }

    /**
     * 将short转为高字节在前，低字节在后的byte数组
     * @param n short
     * @return byte[]
     */
    public static byte[] toHH(short n) {
        byte[] b = new byte[2];
        b[1] = (byte) (n & 0xff);
        b[0] = (byte) (n >> 8 & 0xff);
        return b;
    }

    /**
     * 将float转为低字节在前，高字节在后的byte数组
     * @param f
     * @return
     */
    public static byte[] toLH(float f) {
        return toLH(Float.floatToRawIntBits(f));
    }

    /**
     * 将float转为高字节在前，低字节在后的byte数组
     * @param f
     * @return
     */
    public static byte[] toHH(float f) {
        return toHH(Float.floatToRawIntBits(f));
    }

    /**
     * 将String转为byte数组
     * @param s
     * @param length
     * @return
     */
    public static byte[] stringToBytes(String s, int length) {
        StringBuilder bld = new StringBuilder();
        bld.append(s);
        while (s.length() < length) {
            bld.append("\0");
        }
        return bld.toString().getBytes(Charset.forName("GBK"));
    }

    /**
     * 将字节数组转换为String
     * @param b
     * @return
     */
    public static String bytesToHexString(byte[] b) {
        StringBuilder result = new StringBuilder();
        int length = b.length;
        for (int i = 0; i < length; i++) {
            String temp;
            if (b[i] < 0) {
                temp = String.format("%02x", b[i] + 256);
            } else {
                temp = String.format("%02x", b[i]);
            }
            result.append(temp);
            result.append(" ");
        }
        result.deleteCharAt(result.length() - 1);
        return result.toString();
    }

    /**
     * 将字符串转换为byte数组
     * @param s
     * @return
     */
    public static byte[] stringToBytes(String s) {
        return s.getBytes();
    }

    /**
     * 将高字节数组转换为int
     * @param b
     * @return
     */
    public static int hBytesToInt(byte[] b) {
        int s = 0;
        for (int i = 0; i < 3; i++) {
            if (b[i] >= 0) {
                s = s + b[i];
            } else {
                s = s + 256 + b[i];
            }
            s = s * 256;
        }
        if (b[3] >= 0) {
            s = s + b[3];
        } else {
            s = s + 256 + b[3];
        }
        return s;
    }

    /**
     * 将低字节数组转换为int
     * @param b
     * @return
     */
    public static int lBytesToInt(byte[] b) {
        int s = 0;
        for (int i = 0; i < 3; i++) {
            if (b[3 - i] >= 0) {
                s = s + b[3 - i];
            } else {
                s = s + 256 + b[3 - i];
            }
            s = s * 256;
        }
        if (b[0] >= 0) {
            s = s + b[0];
        } else {
            s = s + 256 + b[0];
        }
        return s;
    }

    /**
     * 高字节数组到short的转换
     * @param b
     * @return
     */
    public static short hBytesToShort(byte[] b) {
        int s = 0;
        if (b[0] >= 0) {
            s = s + b[0];
        } else {
            s = s + 256 + b[0];
        }
        s = s * 256;
        if (b[1] >= 0) {
            s = s + b[1];
        } else {
            s = s + 256 + b[1];
        }
        return (short) s;
    }

    /**
     * 低字节数组到short的转换
     * @param b
     * @return
     */
    public static short lBytesToShort(byte[] b) {
        int s = 0;
        if (b[1] >= 0) {
            s = s + b[1];
        } else {
            s = s + 256 + b[1];
        }
        s = s * 256;
        if (b[0] >= 0) {
            s = s + b[0];
        } else {
            s = s + 256 + b[0];
        }
        return (short) s;
    }

    /**
     * 高字节数组转换为float
     * @param b
     * @return
     */
    public static float hBytesToFloat(byte[] b) {
        int i = 0;
        i = ((((b[0] & 0xff) << 8 | (b[1] & 0xff)) << 8) | (b[2] & 0xff)) << 8 | (b[3] & 0xff);
        return Float.intBitsToFloat(i);
    }

    /**
     * 低字节数组转换为float
     * @param b byte[]
     * @return float
     */
    public static float lBytesToFloat(byte[] b) {
        int i = 0;
        i = ((((b[3] & 0xff) << 8 | (b[2] & 0xff)) << 8) | (b[1] & 0xff)) << 8 | (b[0] & 0xff);
        return Float.intBitsToFloat(i);
    }

    /**
     * 将byte数组中的元素倒序排列
     * @param b
     * @return
     */
    public static byte[] bytesReverseOrder(byte[] b) {
        int length = b.length;
        byte[] result = new byte[length];
        for (int i = 0; i < length; i++) {
            result[length - i - 1] = b[i];
        }
        return result;
    }

    /**
     * 将int类型的值转换为字节序颠倒过来对应的int值
     * @param i int
     * @return int
     */
    public static int reverseInt(int i) {

        return FormatTransfer.hBytesToInt(FormatTransfer.toLH(i));
    }

    /**
     * 将short类型的值转换为字节序颠倒过来对应的short值
     * @param s short
     * @return short
     */
    public static short reverseShort(short s) {

        return FormatTransfer.hBytesToShort(FormatTransfer.toLH(s));
    }

    /**
     * 将float类型的值转换为字节序颠倒过来对应的float值
     * @param f float
     * @return float
     */
    public static float reverseFloat(float f) {

        return FormatTransfer.hBytesToFloat(FormatTransfer.toLH(f));
    }

    /**
     * 将byte数组转换为string
     * @param b
     * @return
     */
    public static String bytesToString(byte[] b) {
        String strOutput = null;
        int length = b.length;
        int i = 0;
        for (i = 0; i < length; i++) {
            if (b[i] == 0) {
                break;
            }
        }

        byte[] data = new byte[i];
        System.arraycopy(b, 0, data, 0, i);

        try {
            strOutput = new String(data, "GBK");
        } catch (UnsupportedEncodingException e) {
            logger.error(e.getMessage(), e);
        }

        return strOutput;
    }

    /**
     * 将字节数组直接转化为字符串
     * @param b
     * @return
     */
    public static String bytes2String(byte[] b) {
        StringBuilder result = new StringBuilder();
        int length = b.length;
        for (int i = 0; i < length; i++) {

            result.append(b[i]);
            result.append(" ");
        }
        result.deleteCharAt(result.length() - 1);
        return result.toString();
    }

    /**
     * 将图片转化成字节数组
     * @param filePath 图片路径
     * @return
     */
    public static byte[] fileToBytes(String filePath) {
        File file = new File(filePath);
        byte[] bs = null;
        try (FileInputStream in = new FileInputStream(file)) {
            int len = in.available();
            bs = new byte[len];
            in.read(bs, 0, len);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return bs;
    }

    /**
     * 将字节字符串直接为byte数组
     * @param s
     * @return
     */
    public static byte[] byteStringToBytes(String s) {
        String[] temp = s.split(" ");
        byte[] result = new byte[temp.length];
        for (int i = 0; i < result.length; i++) {
            result[i] = Byte.valueOf(temp[i]);
        }
        return result;
    }

    /**
     * 将byte流转换成对应的图片
     * @param bytes
     * @param filePath
     */
    public static void bytesToFile(byte[] bytes, String filePath) {
        try (FileOutputStream outputStream = new FileOutputStream(filePath)) {
            outputStream.write(bytes);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
    }
}
